//
//  ui.cpp
//  trail-map-editor
//
//  Created by Giorgio Tino on 2/28/13.
//
//

#if UL_MAC_OSX
#import <mach-o/dyld.h>
#import <stdlib.h>
#import <string.h>
#import <Foundation/Foundation.h>
#endif

#include <plib/pu.h>
#include <plib/puAux.h>

#include "ui.h"

#define UICLASS_GROUP ( PUCLASS_GROUP | PUCLASS_OBJECT | PUCLASS_VALUE )

static char* _glExtensions;

void uiInit()
{
    uiTextureManager* tm = new uiTextureManager();
	
	Log.write(Renderer,"OpenGL Version : %s", uiGetGLVersion());
	
	_glExtensions = uiGetGLExtensions();
	
	puInit();
}

void uiExit()
{
	puExit();
}

void uiCleanUpUserData(puObject* object, const bool recursive)
{
	if(!object)
		return;
	
	puObject* current = object;
	
	while(current)
	{
		if(recursive && (current->getType() == UICLASS_GROUP))
		{
			puGroup* group = (puGroup*)current;
			uiCleanUpUserData(group->getFirstChild(), recursive);
		}
		else if(current->getType() & PUCLASS_MENUBAR)
		{
			uiMenuBar* menuBar = (uiMenuBar*)current; // of course it HAS to be a uiMenuBar!
			
			menuBar->cleanUpUserData();
		}
		else if(current->getType() & PUCLASS_VERTMENU)
		{
			uiVerticalMenu* verticalMenu = (uiVerticalMenu*)current; // of course it HAS to be a uiVerticalMenu!
			
			verticalMenu->cleanUpUserData();
		}
		
		uiData* data = (uiData*)current->getUserData();
		
		if(data)
		{
			delete data;
			data = 0;
			current->setUserData(0);
		}
			
		current = current->getNextObject();
	}
}

const puObject* uiFindByName(const puObject* object, const char* name)
{
	if(!name || !object)
		return 0;
	
	const puObject* current = object;
	
	while(current)
	{
		const puObject* found = NULL;
		
		// This must be exactly 'a group', not just 'a kind of a group'...
        if(current->getType() == UICLASS_GROUP)
        {
            puGroup* group = (puGroup*)current;
            
			//printf("%s : %p (%s)-> %p (%s)\n",name,group,group->getTypeString(), group->getFirstChild(), group->getFirstChild() ? group->getFirstChild()->getTypeString() : "NULL");
            
            found = uiFindByName(group->getFirstChild(), name);
        }
        else if(current->getType() & PUCLASS_MENUBAR)
		{
			uiMenuBar* menuBar = (uiMenuBar*)current; // of course it HAS to be a uiMenuBar!
			
			found = menuBar->findByName(name);
		}
		else if(current->getType() & PUCLASS_VERTMENU)
		{
			uiVerticalMenu* verticalMenu = (uiVerticalMenu*)current; // of course it HAS to be a uiVerticalMenu!
			
			found = verticalMenu->findByName(name);
		}
		
		if(found)
		{
			return found;
		}
		else
		{
			uiData* data = (uiData*)current->getUserData();
			
			if(data && data->name)
			{
				if(ulStrEqual(data->name,name))
					return current;
			}
		}
		
		current = current->getNextObject();
	}
	
	return 0;
}

char* uiGetGLVersion()
{
	return ( char* )glGetString( GL_VERSION );
}

char* uiGetGLExtensions()
{
	return ( char* )glGetString( GL_EXTENSIONS );
}

bool uiCheckGLExtension(const char * extensionName)
{
	unsigned int uiNextExtension;
	char*		 szSupExt = _glExtensions;
	char*		 cEndExtensions;
	
	//find the end of the extension list
	cEndExtensions= szSupExt+strlen( _glExtensions );
	
	//search through the entire list
	while( szSupExt<cEndExtensions )
	{
		//find the next extension in the list
		uiNextExtension= strcspn( szSupExt, " " );
		
		//check the extension to the one given in the argument list
		if( ( strlen( extensionName )==uiNextExtension ) && 
		   ( strncmp( extensionName, szSupExt, uiNextExtension )==0 ) )
		{
			//the extension is supported
			Log.write( Renderer, "Your video card supports extension: %s", extensionName );
			return true;
		}
		
		//move to the nexte extension in the list
		szSupExt+= ( uiNextExtension+1 );
	}

	//the extension is supported
	Log.write( Renderer, "Your video card does not support extension: %s", extensionName );
	return false;
}

void * uiGetGLProcAddress(const char * name)
{	
//	NSSymbol symbol;
//
//	char *symbolName;
//	
//	symbolName = malloc (strlen (name) + 2); // 1
//	
//	strcpy(symbolName + 1, name); // 2
//	
//	symbolName[0] = '_'; // 3
//	
//	symbol = NULL;
//	
//	if (NSIsSymbolNameDefined (symbolName)) // 4
//		
//		symbol = NSLookupAndBindSymbol (symbolName);
//	
//	free (symbolName); // 5
//	
//	return symbol ? NSAddressOfSymbol (symbol) : NULL; // 6
	
	return NULL;
}

char *uiStrCat ( const char *s1, const char* s2)
{
	int s1_sz = strlen ( s1 );
	int s2_sz = strlen ( s2 );
	int tot_sz = s1_sz + s2_sz + 1;
	char *ret = new char [ tot_sz ] ;
	
	memcpy ( ret, s1, s1_sz ) ;
	memcpy ( ret + s1_sz, s2, s2_sz + 1 ) ;
	return ret ;
}

char *uiMakeResourcePath(const char *filename)
{
    char dir[512]; // current working directory
    ulGetCWD(dir, 512);
    
    int dir_sz = strlen(dir);
    int filename_sz = strlen(filename);
    int slash_sz = 2; // NOTE : 1 for uniz sistems, 2 for windows
    int tot_sz = dir_sz + filename_sz + slash_sz + 1;
    char* path = new char[tot_sz];
    
    return ulMakePath(path, dir, filename);
}